#include <casgi/CASGIE.h>

// ***********************************************************************

// class EDROOMTopContext

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CASGI::EDROOMTopContext::EDROOMTopContext (CASGI &act, word32_t & EDROOMpVarVAcks, byte_t & EDROOMpVarVAltBit, bool_t & EDROOMpVarVAlternate, CDBurst & EDROOMpVarVBurst, CDDataBurst & EDROOMpVarVDataBurst, CPackListHandler & EDROOMpVarVFreePackList, bool_t & EDROOMpVarVIsSatControl, bool_t & EDROOMpVarVIsSenTMTCDelivery, bool_t & EDROOMpVarVLastTCBurst, bool_t & EDROOMpVarVLastTMBurst, bool_t & EDROOMpVarVLinkLost, word32_t & EDROOMpVarVSizeProvide, word32_t & EDROOMpVarVSizeReq, word32_t & EDROOMpVarVStatsRx, word32_t & EDROOMpVarVStatsTx, CPackListHandler & EDROOMpVarVTCPackList, CPackListHandler & EDROOMpVarVTMPackList, int32_t & EDROOMpVarVTryNumber, CEDROOMPOOLCDTMTCCommServer & EDROOMpPoolCDTMTCCommServer, CEDROOMPOOLCDDataBurst & EDROOMpPoolCDDataBurst, CEDROOMPOOLCDBurst & EDROOMpPoolCDBurst ):

	EDROOMcomponent(act)
	,Msg(EDROOMcomponent.Msg)
	,MsgBack(EDROOMcomponent.MsgBack)
	,PlannerSGIControl(EDROOMcomponent.PlannerSGIControl)
	,SgiTMTCServer(EDROOMcomponent.SgiTMTCServer)
	,SGIComm(EDROOMcomponent.SGIComm)
	,SATReadyTimer(EDROOMcomponent.SATReadyTimer)
	,TxRxBurstTimer(EDROOMcomponent.TxRxBurstTimer)
	, VAcks ( EDROOMpVarVAcks )
	, VAltBit ( EDROOMpVarVAltBit )
	, VAlternate ( EDROOMpVarVAlternate )
	, VBurst ( EDROOMpVarVBurst )
	, VDataBurst ( EDROOMpVarVDataBurst )
	, VFreePackList ( EDROOMpVarVFreePackList )
	, VIsSatControl ( EDROOMpVarVIsSatControl )
	, VIsSenTMTCDelivery ( EDROOMpVarVIsSenTMTCDelivery )
	, VLastTCBurst ( EDROOMpVarVLastTCBurst )
	, VLastTMBurst ( EDROOMpVarVLastTMBurst )
	, VLinkLost ( EDROOMpVarVLinkLost )
	, VSizeProvide ( EDROOMpVarVSizeProvide )
	, VSizeReq ( EDROOMpVarVSizeReq )
	, VStatsRx ( EDROOMpVarVStatsRx )
	, VStatsTx ( EDROOMpVarVStatsTx )
	, VTCPackList ( EDROOMpVarVTCPackList )
	, VTMPackList ( EDROOMpVarVTMPackList )
	, VTryNumber ( EDROOMpVarVTryNumber )
	, EDROOMPoolCDTMTCCommServer ( EDROOMpPoolCDTMTCCommServer )
	, EDROOMPoolCDDataBurst ( EDROOMpPoolCDDataBurst )
	, EDROOMPoolCDBurst ( EDROOMpPoolCDBurst )
 {

}

CASGI::EDROOMTopContext::EDROOMTopContext ( EDROOMTopContext &contex ):

	EDROOMcomponent(contex.EDROOMcomponent),
	Msg(contex.Msg),
	MsgBack(contex.MsgBack)
	,PlannerSGIControl(contex.PlannerSGIControl)
	,SgiTMTCServer(contex.SgiTMTCServer)
	,SGIComm(contex.SGIComm)
	,SATReadyTimer(contex.SATReadyTimer)
	,TxRxBurstTimer(contex.TxRxBurstTimer)
	, VAcks ( contex.VAcks )
	, VAltBit ( contex.VAltBit )
	, VAlternate ( contex.VAlternate )
	, VBurst ( contex.VBurst )
	, VDataBurst ( contex.VDataBurst )
	, VFreePackList ( contex.VFreePackList )
	, VIsSatControl ( contex.VIsSatControl )
	, VIsSenTMTCDelivery ( contex.VIsSenTMTCDelivery )
	, VLastTCBurst ( contex.VLastTCBurst )
	, VLastTMBurst ( contex.VLastTMBurst )
	, VLinkLost ( contex.VLinkLost )
	, VSizeProvide ( contex.VSizeProvide )
	, VSizeReq ( contex.VSizeReq )
	, VStatsRx ( contex.VStatsRx )
	, VStatsTx ( contex.VStatsTx )
	, VTCPackList ( contex.VTCPackList )
	, VTMPackList ( contex.VTMPackList )
	, VTryNumber ( contex.VTryNumber )
	, EDROOMPoolCDTMTCCommServer ( contex.EDROOMPoolCDTMTCCommServer )
	, EDROOMPoolCDDataBurst ( contex.EDROOMPoolCDDataBurst )
	, EDROOMPoolCDBurst ( contex.EDROOMPoolCDBurst )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CASGI::EDROOMTopContext::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case (SKeepOnComm): 

				if ( *Msg->GetPInterface() == PlannerSGIControl) {

					edroomCurrentTrans.localId= KeepOnComm;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

			 break;

		 case (SToStandBy): 

				if ( *Msg->GetPInterface() == PlannerSGIControl) {

					edroomCurrentTrans.localId= ToStandBy;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

			 break;

		 case ( EDROOMSignalDestroy ): 

			 edroomValidMsg=true;
			 edroomCurrentTrans.distanceToContext = 0 ;
			 edroomCurrentTrans.localId = -1 ;
			 break;

	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

void	CASGI::EDROOMTopContext::FBurstError()

{
 
	VTryNumber++;
	if (VTryNumber >= 5)//==
	{
		DEBUG("VTryNumber > 5\n");
		VLinkLost = true;
		VTryNumber = 0;
	}
 
}
 



word16_t	CASGI::EDROOMTopContext::FCalculateTMToCopy()

{
	if (VIsSenTMTCDelivery)
	{
		if ((VSizeReq / 256) >= 32)//the request wants more, or equal, of 32 frames
		{
			return 32;
		}
		else
		{
			return (VSizeReq / 256);
		}
	}
	else
	{
		return 32;
	}
 
}



void	CASGI::EDROOMTopContext::FCalculateTMToProvide()

{
 
	if ((VSizeReq / 256) > VTMPackList.GetPackCounter())//the request wants more, or equal, of 32 frames
	{
		VSizeReq = VTMPackList.GetPackCounter()*256;
	}
 
 
}



void	CASGI::EDROOMTopContext::FCheckTCAcks(bool_t *pAcksOk, bool_t *pAllOk, byte_t nNum, CPackListHandler & packList)

{
 
	uint8_t j = 0;
	CPackHandler newPackHandler;
 
	packList.ToHeadPack();
	if (packList.GetPackCounter())
	{
		do
		{
			packList.GetCurrentReadPack(newPackHandler);
			if (newPackHandler.CheckCRC(0, 254))
			{
				pAcksOk[j] = true;
			}
			else
			{
				(*pAllOk) = false;
			}
			j++;
		}
		while ((j <nNum) && (packList.NextReadPack()));
	}
 
}
 



void	CASGI::EDROOMTopContext::FCommInterrupted()

{
 
	FSendTCPacketsToTMTCServer();
	// send new Msg
 
	PlannerSGIControl.send(SCommInterrupted, EDROOMprioNormal);
 
}



void	CASGI::EDROOMTopContext::FCopyList()

 
{
	byte_t newPack[256];
	word16_t tmToProvide=0;
	uint16_t i=0;
	CPackHandler newReadPackHandler;
	CPackHandler newEditPackHandler;
 
 
	tmToProvide=FCalculateTMToCopy();
	//TODO: Hacer esta comprobacion de >=32 en el resto de metodos similares
	VTMPackList.ToHeadPack();
	VFreePackList.ToHeadPack();
	VDataBurst.packList.ToHeadPack();
	if (VTMPackList.GetPackCounter() && (VFreePackList.GetPackCounter() >= 32))
	{
		VFreePackList.ExtractPackages(tmToProvide,VDataBurst.packList);
		do
		{
			VDataBurst.packList.GetCurrentEditPack(newEditPackHandler);
			VTMPackList.GetCurrentReadPack(newReadPackHandler);
			for (i = 0; i < 256; i++)
			{
				newReadPackHandler.ReadByte(i, newPack[i]);
				newEditPackHandler.WriteByte(i, newPack[i]);
			}
			VDataBurst.packList.NextEditPack();
			tmToProvide--;
		}
		while (VTMPackList.NextReadPack() && tmToProvide > 0);
	}
 
 
}



void	CASGI::EDROOMTopContext::FInitCommConf()

{
 
	VLinkLost = false;
	VAlternate = true;
	VLastTCBurst = false;
	VLastTMBurst = false;
	VIsSatControl = false;
	VIsSenTMTCDelivery = false;
}



void	CASGI::EDROOMTopContext::FKeepOnComm()

{
 
	// reply
	Msg->reply(SCommConfigured);
}



void	CASGI::EDROOMTopContext::FProgSATReady()

 
{
	float timeToStandby= 0.1;
	Pr_Time	wait(timeToStandby);
 
	while (!bufferOfDeviceIndex)
	{
		VTryNumber = 0;
		Pr_DelayIn(wait);
	}
 
 
	//Initialize communitaction configuration
	FInitCommConf();
 
	//TODO: faltaria la lista con los datos a enviar en READY
	sgi_link_layer_build_sgi_ready_burst(VDataBurst.header, 0, VAlternate, &VAltBit);
	
	//TODO: hay que definir la velocidad de env?o de r?fagas
	Pr_Time interval(0.01); // Declare time var with an initial value in seconds
	SATReadyTimer.InformIn(interval, EDROOMprioNormal);
 
}



void	CASGI::EDROOMTopContext::FReceiveTC(CDDataBurst dataBurst)

{
	
	bool_t bAcksOk[32];
	bool_t bAllOk = true;
	int8_t nOffSet = 0;
	uint8_t i = 0;
 
	for (i = 0; i < 32; i++)
	{
		bAcksOk[i] = false;
	}
 
	sgi_link_layer_check_crcs(dataBurst.header, &nOffSet);
	VTryNumber = 0;
	FCheckTCAcks(bAcksOk, &bAllOk, sgi_link_layer_get_nf(dataBurst.header + nOffSet), dataBurst.packList);
	VAcks = set_acks(bAcksOk);
					//Esta funci?n tambi?n vale para el last_sen_tc porque poseen la misma m?scara
	VLastTCBurst = (sgi_link_layer_is_last_sat_tc_frames(dataBurst.header + nOffSet) && bAllOk);
 
}



void	CASGI::EDROOMTopContext::FRequestTCList()

 
 
{
 CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
	
		// Complete Data 
	
	ap_CDTMTCCommServer->sizeProvide=0;
	ap_CDTMTCCommServer->packListRequest=false;
	
		// invoke 
	
	MsgBack=SgiTMTCServer.invoke(STCPackList, EDROOMprioVeryHigh, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
	
		// Handling MsgBack
	
		// Handling MsgBack
	CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *) MsgBack->data;
 
	VTCPackList = varCDTMTCCommServer.packList1;
	VTCPackList.ToHeadPack();
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
 
 
}



void	CASGI::EDROOMTopContext::FRequestTCList(word32_t &sizeProv)

 
{
 
	CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
	
		// Complete Data 
	
	ap_CDTMTCCommServer->sizeProvide=(sizeProv/256);
	ap_CDTMTCCommServer->packListRequest=true;
	
		// invoke 
	
	MsgBack=SgiTMTCServer.invoke(STCPackList, EDROOMprioVeryHigh, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
	
		// Handling MsgBack
	
		// Handling MsgBack
	CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *) MsgBack->data;
 
	VTCPackList = varCDTMTCCommServer.packList1;
	VTCPackList.ToHeadPack();
	sizeProv=varCDTMTCCommServer.sizeProvide;
	//VTCPackList= varCDTMTCCommServer.packList2;//The second list is redundant
 
 
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
 
 
}
 
 



void	CASGI::EDROOMTopContext::FSendReady()

 
{
	CDDataBurst * ap_CDDataBurst = EDROOMPoolCDDataBurst.AllocData();
	int8_t nOffSet = 0;
	BurstTypeReceived_t burstType = BurstTypeIsSGIDefault;
	bool_t bCrcOk = false;
 
	(*ap_CDDataBurst) = VDataBurst;
 
	// invoke
	MsgBack = SGIComm.invoke(STxDataBurst, EDROOMprioNormal, ap_CDDataBurst, &EDROOMPoolCDDataBurst);
	// Handling MsgBack
 
	if (MsgBack->signal == SRxDataBurst)
	{
		CDDataBurst & varCDDataBurst = *(CDDataBurst *) MsgBack->data;
		bCrcOk = sgi_link_layer_check_crcs(varCDDataBurst.header, &nOffSet);
		burstType = sgi_link_layer_get_burst_type(varCDDataBurst.header + nOffSet);
		if ((bCrcOk) && (burstType == BurstTypeIsSatTCFrames))
		{
			VIsSatControl = true;
			FRequestTCList();
			FReceiveTC(varCDDataBurst);
			FStoreReceiveTC(varCDDataBurst);
		}
		else
		{
			FBurstError();//TODO: revisar, creo que para el caso de ready no es
			//del todo necesario (ver transparencia 46 de SRG_HUMSAT_SGI), si se deja as?
			// es por informar al planner
		}
	}
	else if (MsgBack->signal == SRxBurst)//Receive SAT_BURST_NACK or CODE B
	{
		CDBurst & varCDBurst = *(CDBurst *) MsgBack->data;
		bCrcOk = sgi_link_layer_check_crcs(varCDBurst.header, &nOffSet);
		burstType = sgi_link_layer_get_burst_type(varCDBurst.header + nOffSet);
 
		if ((bCrcOk) && (burstType == BurstTypeIsSatBurstNack))
		{
			VTryNumber = 0;//TODO: AQUI  TRYNUMBER 0 NO
			//AQU? QUE PASAAAAAAAABA? creo que deber?a ser tambi?n BurstError
		}
		else if ((bCrcOk) && (burstType == BurstTypeIsSenTMTCDelReq))
		{
			VIsSenTMTCDelivery = true;
			VSizeReq = sgi_link_layer_get_size_req(varCDBurst.header + nOffSet);
			VSizeProvide = sgi_link_layer_get_size_provide(varCDBurst.header + nOffSet);
			FRequestTCList(VSizeProvide);
			if (VSizeReq==0)
			{
				VLastTMBurst=true;
			}
		}
		else
		{
			FBurstError();
		}
	}
	else//SNoAnswer
	{
		FBurstError();
		if (MsgBack->signal == SNoAnswer)
		{
			VAlternate = false;
		}
	}
	// End Handling MsgBack
	EDROOMFreeMsgBack(MsgBack);
 
}
 



void	CASGI::EDROOMTopContext::FSendTCPacketsToTMTCServer()

 
{
	uint16_t i=0;
	uint16_t j=0;
	CPackHandler packAux;
	// send new Msg
	CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
 
	VDataBurst.packList.ExtractAllPackages(VFreePackList);
 
	VFreePackList.ToHeadPack();
	for (j=0;j<VFreePackList.GetPackCounter();j++)
	{
		VFreePackList.GetCurrentEditPack(packAux);
		for (i=0;i<256;i++)
		{
			packAux.WriteByte(i,0);
		}
		VFreePackList.NextEditPack();
	}
	VTMPackList.ExtractAllPackages(VFreePackList);
 
 
	// Complete Data
	ap_CDTMTCCommServer->packList1 = VTCPackList;//To send packets from the TCs extracted
	ap_CDTMTCCommServer->packList2 = VFreePackList;//To send packets from the TCs extracted
 
 
	// invoke
	MsgBack = SgiTMTCServer.invoke(SFinalTCPackets, EDROOMprioNormal, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
	// Handling MsgBack
	CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *)Msg->data;
 
	VTCPackList=varCDTMTCCommServer.packList1;
 
	// End Handling MsgBack
	EDROOMFreeMsgBack(MsgBack);
}



void	CASGI::EDROOMTopContext::FStoreReceiveTC(CDDataBurst & dataBurst)

{
	uint8_t nNum = 0;
	byte_t newByte=0;
	CPackHandler newReadPackHandler;
	CPackHandler newEditPackHandler;
	uint16_t i = 0;
 
	dataBurst.packList.ToHeadPack();
	if (dataBurst.packList.GetPackCounter())
	{
		do
		{
			if (((VAcks >> nNum) & 0x01) == 0x01)
			{
 
				VTCPackList.GetCurrentEditPack(newEditPackHandler);
				dataBurst.packList.GetCurrentReadPack(newReadPackHandler);
				for (i = 0; i < 256; i++)
				{
					newReadPackHandler.ReadByte(i, newByte);
					newEditPackHandler.WriteByte(i, newByte);
				}
			}
			VTCPackList.NextEditPack();
			nNum++;
		}
		while (dataBurst.packList.NextReadPack() && (nNum < 32));
	}
 
}
 



void	CASGI::EDROOMTopContext::FToComm()

{
 
	Msg->reply(SCommConfigured);
 
}
 



void	CASGI::EDROOMTopContext::FToStandby()

{
 
}



bool_t	CASGI::EDROOMTopContext::GEnConstruccion()

 
{
 
	return false;
}



bool_t	CASGI::EDROOMTopContext::GIsSatControl()

{
	return (VIsSatControl && !(VLinkLost));
}



bool_t	CASGI::EDROOMTopContext::GIsSenTMTCDelivery()

{
	return (VIsSenTMTCDelivery && !(VLinkLost));
}



bool_t	CASGI::EDROOMTopContext::GLinkLost()

{
	return VLinkLost;
}



// ***********************************************************************

// class EDROOM_CTX_SATControl_3

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CASGI::EDROOM_CTX_SATControl_3::EDROOM_CTX_SATControl_3( EDROOMTopContext &contex ):

	EDROOMTopContext(contex)
{

}

CASGI::EDROOM_CTX_SATControl_3::EDROOM_CTX_SATControl_3( EDROOM_CTX_SATControl_3 &contex ):

	EDROOMTopContext(contex)
 {

}

	// EDROOMSearchContextTrans********************************************

bool CASGI::EDROOM_CTX_SATControl_3::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 if (!edroomValidMsg){

	 }

	if (!edroomValidMsg) {

		 edroomValidMsg = EDROOMTopContext::EDROOMSearchContextTrans(edroomCurrentTrans);
		 if (edroomValidMsg) edroomCurrentTrans.distanceToContext++;
	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

void	CASGI::EDROOM_CTX_SATControl_3::FProgSATTC()

{
	float timeToStandby= 0.1;
	Pr_Time	wait(timeToStandby);
 
	while (!bufferOfDeviceIndex)
	{
		Pr_DelayIn(wait);
	}
	//Build SAT_TC_ACK
	if (!VLastTCBurst)
	{
		sgi_link_layer_build_tc_ack(VBurst.header, VAcks, VAlternate, VTryNumber, &VAltBit);
	}
 
	Pr_Time interval(0.01); // Declare time var with an initial value in seconds
	TxRxBurstTimer.InformIn(interval, EDROOMprioNormal);
 
 
}



void	CASGI::EDROOM_CTX_SATControl_3::FProgSATTM()

 
 
{
	float timeToStandby= 0.1;
	Pr_Time	wait(timeToStandby);
 
	while (!bufferOfDeviceIndex)
	{
		Pr_DelayIn(wait);
	}
	//IMPORTANT: The first TM must have TCAcks
	if (VTryNumber == 0)//if the burst is not repeat
	{
		// send new Msg
		CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
 
 
		// Complete Data
		ap_CDTMTCCommServer->packList1 = VTMPackList;
		ap_CDTMTCCommServer->packList2 = VFreePackList;
 
		/**
		 * TODO TODO TODO!!!: usar el packListRequest
		 */
 
 
		// invoke
		MsgBack = SgiTMTCServer.invoke(STMDoublePackList, EDROOMprioNormal, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
 
 
		// Handling MsgBack
		CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *) MsgBack->data;
 
		VTMPackList = varCDTMTCCommServer.packList1;
		VFreePackList = varCDTMTCCommServer.packList2;
 
 
		// End Handling MsgBack
		EDROOMFreeMsgBack(MsgBack);
 
 
		//Build the new TM burst
		FCopyList();
		//Si no es LAST, si es LAST < 32
 
	}
	sgi_link_layer_build_header_tm_frame(VDataBurst.header,VAcks ,VTMPackList.GetPackCounter(), VAlternate, VTryNumber, &VAltBit);
 
	Pr_Time interval(0.01); // Declare time var with an initial value in seconds
	TxRxBurstTimer.InformIn(interval, EDROOMprioNormal);
 
 
}
 



void	CASGI::EDROOM_CTX_SATControl_3::FSendTCAck()

 
{
 
	int8_t nOffSet=0;
	VAlternate = true;
	bool_t bCrcOk = false;
	BurstTypeReceived_t burstType = BurstTypeIsSGIDefault;
 
	if (!VLastTCBurst)
	{
		// Complete Data
		CDBurst * ap_CDBurst = EDROOMPoolCDBurst.AllocData();
		(*ap_CDBurst) = VBurst;
		// invoke
		MsgBack = SGIComm.invoke(STxBurst, EDROOMprioNormal, ap_CDBurst, &EDROOMPoolCDBurst);
		// Handling MsgBack
		if (MsgBack->signal == SRxDataBurst)
		{
			CDDataBurst & varCDDataBurst = *(CDDataBurst *) MsgBack->data;
 
			bCrcOk = sgi_link_layer_check_crcs(varCDDataBurst.header, &nOffSet);
			burstType = sgi_link_layer_get_burst_type(varCDDataBurst.header + nOffSet);
			if ((bCrcOk) && (burstType == BurstTypeIsSatTCFrames))
			{
				FReceiveTC(varCDDataBurst);
				FStoreReceiveTC(varCDDataBurst);
			}
			else
			{
				FBurstError();
			}
		}
		else
		{
			FBurstError();
			if (MsgBack->signal == SNoAnswer)
			{
				VAlternate = false;
			}
		}
		// End Handling MsgBack
		EDROOMFreeMsgBack(MsgBack);
	}
}
 



void	CASGI::EDROOM_CTX_SATControl_3::FSendTM()

 
 
{
	CDDataBurst * ap_CDDataBurst = EDROOMPoolCDDataBurst.AllocData();
	int8_t nOffSet=0;
	byte_t nPacksNumber = 32;
	bool_t bCrcOk = false;
	BurstTypeReceived_t burstType = BurstTypeIsSGIDefault;
	word32_t acksAux = 0;
 
	(*ap_CDDataBurst) = VDataBurst;
	// invoke
	MsgBack = SGIComm.invoke(STxDataBurst, EDROOMprioNormal, ap_CDDataBurst, &EDROOMPoolCDDataBurst);
	// Handling MsgBack
	if (MsgBack->signal == SRxBurst)
	{
		CDBurst & varCDBurst = *(CDBurst *) MsgBack->data;
		bCrcOk = sgi_link_layer_check_crcs(varCDBurst.header, &nOffSet);
		burstType = sgi_link_layer_get_burst_type(varCDBurst.header + nOffSet);
		if ((bCrcOk) && (burstType == BurstTypeIsSatTMFramesAck))
		{
			VTryNumber = 0;
			acksAux = sgi_link_layer_get_acks(varCDBurst.header + nOffSet);
 
			VDataBurst.packList.ExtractAllPackages(VFreePackList);//To recover memory from packets
			VTMPackList.ExtractPackages(acksAux, nPacksNumber, VFreePackList);
 
			if (sgi_link_layer_is_last_sat_tm_frames_ack(varCDBurst.header) && VTMPackList.GetPackCounter() == 0)
			{
				VLastTMBurst = true;
			}
		}
		else
		{
			FBurstError();
		}
 
	}
	// End Handling MsgBack
	EDROOMFreeMsgBack(MsgBack);
 
}
 



void	CASGI::EDROOM_CTX_SATControl_3::FTxTMCompleted()

{
	FSendTCPacketsToTMTCServer();
	// send new Msg
	PlannerSGIControl.send(STMTransmited, EDROOMprioNormal);
}



bool_t	CASGI::EDROOM_CTX_SATControl_3::GIsNotLastTCBurst()

{
	return (!VLastTCBurst && !VLinkLost);
}
 



bool_t	CASGI::EDROOM_CTX_SATControl_3::GLastTMBurst()

{
	return (!VLastTMBurst);
}



// ***********************************************************************

// class EDROOM_CTX_SenTMTCDelivery_4

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CASGI::EDROOM_CTX_SenTMTCDelivery_4::EDROOM_CTX_SenTMTCDelivery_4( EDROOMTopContext &contex, BurstTypeReceived_t & EDROOMpVarVBurstType, bool_t & EDROOMpVarVSendDel ):

	EDROOMTopContext(contex)
	, VBurstType ( EDROOMpVarVBurstType )
	, VSendDel ( EDROOMpVarVSendDel )
{

}

CASGI::EDROOM_CTX_SenTMTCDelivery_4::EDROOM_CTX_SenTMTCDelivery_4( EDROOM_CTX_SenTMTCDelivery_4 &contex ):

	EDROOMTopContext(contex)
	, VBurstType ( contex.VBurstType )
	, VSendDel ( contex.VSendDel )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CASGI::EDROOM_CTX_SenTMTCDelivery_4::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 if (!edroomValidMsg){

	 }

	if (!edroomValidMsg) {

		 edroomValidMsg = EDROOMTopContext::EDROOMSearchContextTrans(edroomCurrentTrans);
		 if (edroomValidMsg) edroomCurrentTrans.distanceToContext++;
	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

void	CASGI::EDROOM_CTX_SenTMTCDelivery_4::FProgAccept()

 
{
 
	float timeToStandby= 0.1;
	Pr_Time	wait(timeToStandby);
 
	while (!bufferOfDeviceIndex)
	{
		Pr_DelayIn(wait);
	}
 
	if (VTryNumber == 0)
	{
 
		VSendDel = false;
 
		//word32_t sizeReq=0x0;
		if (!VLastTMBurst)
		{
 
			// send new Msg
			CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
 
 
			// Complete Data
			ap_CDTMTCCommServer->packList1 = VTMPackList;
			ap_CDTMTCCommServer->packList2 = VFreePackList;
			ap_CDTMTCCommServer->packListRequest=true;
 
 
			// invoke
			MsgBack = SgiTMTCServer.invoke(STMDoublePackList, EDROOMprioNormal, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
 
 
			// Handling MsgBack
			CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *) MsgBack->data;
 
			VTMPackList = varCDTMTCCommServer.packList1;
			if (varCDTMTCCommServer.packListRequest)
			{
				VFreePackList = varCDTMTCCommServer.packList2;
			}
 
			FCalculateTMToProvide();
 
			if(!VSizeReq)
			{
				VLastTMBurst=true;
			}
 
			// End Handling MsgBack
			EDROOMFreeMsgBack(MsgBack);
		}
 
																											//TODO:aqu? lo suyo ser?a poner VSizeProvide
		sgi_link_layer_build_sen_tm_tc_del_accept(VBurst.header, VAlternate, VTryNumber, &VAltBit,VSizeReq, (VTCPackList.GetPackCounter()*256));
		// Declare time var with an initial value in seconds
	}
	Pr_Time interval(0.01);
	TxRxBurstTimer.InformIn(interval, EDROOMprioNormal);
 
}



void	CASGI::EDROOM_CTX_SenTMTCDelivery_4::FProgSenLoad()

 
{
	float timeToStandby= 0.1;
	Pr_Time	wait(timeToStandby);
 
	while (!bufferOfDeviceIndex)
	{
		Pr_DelayIn(wait);
	}
 
	if (VTryNumber == 0)
	{
		if (VLastTMBurst)
		{
			//send TC ACK
			if (!VLastTCBurst)
			{
				sgi_link_layer_build_sen_tc_sgi_frames_ack(VBurst.header, VAcks, VAlternate, VTryNumber, &VAltBit);
			}
			else
			{
				sgi_link_layer_build_sen_tm_tc_del_end(VBurst.header, VAlternate, VTryNumber, &VAltBit);
			}
 
		}
		else
		{
//			//mandamos TM con TC ACK IMPLICITO
			FCopyList();
			sgi_link_layer_build_sen_tm_sgi_header_frame(VDataBurst.header, VDataBurst.packList.GetPackCounter(), VAlternate, VTryNumber, &VAltBit, VAcks);
 
		}
	}
	Pr_Time interval(0.01); // Declare time var with an initial value in seconds
	TxRxBurstTimer.InformIn(interval, EDROOMprioNormal);
 
}



void	CASGI::EDROOM_CTX_SenTMTCDelivery_4::FSendAccept()

 
 
{
	CDBurst * ap_CDBurst = EDROOMPoolCDBurst.AllocData();
	int8_t nOffSet=0;
	VAlternate = true;
	bool_t bCrcOk = false;
	VBurstType = BurstTypeIsSGIDefault;
	// Complete Data
 
	(*ap_CDBurst) = VBurst;
	// invoke
	MsgBack = SGIComm.invoke(STxBurst, EDROOMprioNormal, ap_CDBurst, &EDROOMPoolCDBurst);
	//sgi_uart_dev_putchar(0x66);
	if (MsgBack->signal == SRxDataBurst)
	{
		CDDataBurst & varCDDataBurst = *(CDDataBurst *) MsgBack->data;
		bCrcOk = sgi_link_layer_check_crcs(varCDDataBurst.header, &nOffSet);
		VBurstType = sgi_link_layer_get_burst_type(varCDDataBurst.header + nOffSet);
		if ((bCrcOk) && (VBurstType == BurstTypeIsSenTCSgiLinkFrames))
		{
			if (sgi_link_layer_get_nf((varCDDataBurst.header + nOffSet)) != 0)
			{
				FReceiveTC(varCDDataBurst);
				FStoreReceiveTC(varCDDataBurst);
			}
			else
			{
				VLastTCBurst = true;
				VAcks = 0xFFFFFFFF;
			}
		}
		else
		{
			FBurstError();
		}
	}
	else
	{
 
		FBurstError();
		if (MsgBack->signal == SNoAnswer)
		{
			VAlternate = false;
		}
	}
	// Handling MsgBack
	EDROOMFreeMsgBack(MsgBack);
}



void	CASGI::EDROOM_CTX_SenTMTCDelivery_4::FSendDown()

 
 
{
	int8_t nOffSet=0;
	byte_t nPacksNumber = 32;
	bool_t bCrcOk = false;
	BurstTypeReceived_t burstType = BurstTypeIsSGIDefault;
	word32_t acksAux = 0;
 
	if (VLastTMBurst)
	{
		CDBurst * ap_CDBurst = EDROOMPoolCDBurst.AllocData();
		(*ap_CDBurst) = VBurst;
		// invoke
		MsgBack = SGIComm.invoke(STxBurst, EDROOMprioNormal, ap_CDBurst, &EDROOMPoolCDBurst);
	}
	else
	{
		CDDataBurst * ap_CDDataBurst = EDROOMPoolCDDataBurst.AllocData();
		(*ap_CDDataBurst) = VDataBurst;
		//nPacksNumber=sgi_link_layer_get_nf(VDataBurst.header);
		nPacksNumber=VDataBurst.packList.GetPackCounter();
		// invoke
		MsgBack = SGIComm.invoke(STxDataBurst, EDROOMprioNormal, ap_CDDataBurst, &EDROOMPoolCDDataBurst);
	}
 
	// Handling MsgBack
	if (MsgBack->signal == SRxDataBurst)
	{
		CDDataBurst & varCDDataBurst = *(CDDataBurst *) MsgBack->data;
		bCrcOk = sgi_link_layer_check_crcs(varCDDataBurst.header, &nOffSet);
		burstType = sgi_link_layer_get_burst_type(varCDDataBurst.header + nOffSet);
		if ((bCrcOk) && (burstType == BurstTypeIsSenTCSgiLinkFrames))
		{
			FReceiveTC(varCDDataBurst);
			FStoreReceiveTC(varCDDataBurst);
			if (!VLastTMBurst)
			{
				acksAux = sgi_link_layer_get_acks(varCDDataBurst.header + nOffSet);
				VDataBurst.packList.ExtractAllPackages(VFreePackList);//Recuperar memoria de los paquetes
				VTMPackList.ExtractPackages(acksAux, nPacksNumber, VFreePackList);
				VSizeReq -= (nPacksNumber * 256);
				if (VSizeReq<= 0)
				{
					VLastTMBurst = true;
				}
			}
		}
		else if ((bCrcOk) && (burstType == BurstTypeIsSenTMSgiLinkFramesAck))
		{
			acksAux = sgi_link_layer_get_acks(varCDDataBurst.header + nOffSet);
			VDataBurst.packList.ExtractAllPackages(VFreePackList);//Recuperar memoria de los paquetes
			VTMPackList.ExtractPackages(acksAux, nPacksNumber, VFreePackList);
			VSizeReq -= (nPacksNumber * 256);
			if ((VSizeReq<= 0) || (sgi_link_layer_is_last_sen_tm_sgi_link_frames_ack(varCDDataBurst.header)))
			{
				VLastTMBurst = true;
			}
		}
		else
		{
			FBurstError();
		}
	}
	else if (MsgBack->signal == SRxBurst)//is the end of TC UpLoad
	{
		CDBurst & varCDBurst = *(CDBurst *) MsgBack->data;
		bCrcOk = sgi_link_layer_check_crcs(varCDBurst.header, &nOffSet);
		burstType = sgi_link_layer_get_burst_type(varCDBurst.header + nOffSet);
		if ((bCrcOk) && (burstType == BurstTypeIsSenTMTCDelEndAck))
		{
			VSendDel = true;
		}
		else
		{
			FBurstError();
		}
	}
	else
	{
		FBurstError();
		if (MsgBack->signal == SNoAnswer)
		{
			VAlternate = false;
		}
	}
	EDROOMFreeMsgBack(MsgBack);
 
}
 



void	CASGI::EDROOM_CTX_SenTMTCDelivery_4::FTxTMTCDeliveryCompleted()

{
	FSendTCPacketsToTMTCServer();
	// send new Msg
	PlannerSGIControl.send(STMTransmited, EDROOMprioNormal);
}



bool_t	CASGI::EDROOM_CTX_SenTMTCDelivery_4::GNotCompleted()

{
	return !(VLastTCBurst && VLastTMBurst && VSendDel);
}



bool_t	CASGI::EDROOM_CTX_SenTMTCDelivery_4::GResponseAccept()

{
	return (VBurstType == BurstTypeIsSenTCSgiLinkFrames);
}



	//*****Pools

	//CEDROOMPOOLCDTMTCCommServer

CASGI::EDROOMTopContext::CEDROOMPOOLCDTMTCCommServer::CEDROOMPOOLCDTMTCCommServer(unsigned int elemCount, CDTMTCCommServer* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDTMTCCommServer)){;}

CDTMTCCommServer *	CASGI::EDROOMTopContext::CEDROOMPOOLCDTMTCCommServer::AllocData(){
	return(CDTMTCCommServer*)CEDROOMProtectedMemoryPool::AllocData();
}

	//CEDROOMPOOLCDDataBurst

CASGI::EDROOMTopContext::CEDROOMPOOLCDDataBurst::CEDROOMPOOLCDDataBurst(unsigned int elemCount, CDDataBurst* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDDataBurst)){;}

CDDataBurst *	CASGI::EDROOMTopContext::CEDROOMPOOLCDDataBurst::AllocData(){
	return(CDDataBurst*)CEDROOMProtectedMemoryPool::AllocData();
}

	//CEDROOMPOOLCDBurst

CASGI::EDROOMTopContext::CEDROOMPOOLCDBurst::CEDROOMPOOLCDBurst(unsigned int elemCount, CDBurst* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDBurst)){;}

CDBurst *	CASGI::EDROOMTopContext::CEDROOMPOOLCDBurst::AllocData(){
	return(CDBurst*)CEDROOMProtectedMemoryPool::AllocData();
}



// ***********************************************************************

// class EDROOMTopState

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CASGI::EDROOMTopState::EDROOMTopState (CASGI &act, CEDROOMMemory *pEDROOMMemory  ):
	  EDROOMTopContext( act , VAcks, VAltBit, VAlternate, VBurst, VDataBurst, VFreePackList, VIsSatControl, VIsSenTMTCDelivery, VLastTCBurst, VLastTMBurst, VLinkLost, VSizeProvide, VSizeReq, VStatsRx, VStatsTx, VTCPackList, VTMPackList, VTryNumber,EDROOMPoolCDTMTCCommServer,EDROOMPoolCDDataBurst,EDROOMPoolCDBurst )
	, EDROOMSATControl( SATControl , *this )
	, EDROOMSenTMTCDelivery( SenTMTCDelivery , *this )
	, VAcks ( 0 )
	, VAltBit ( 0 )
	, VAlternate ( true )
	, VBurst (   )
	, VDataBurst (   )
	, VFreePackList (   )
	, VIsSatControl ( false )
	, VIsSenTMTCDelivery ( false )
	, VLastTCBurst ( false )
	, VLastTMBurst ( false )
	, VLinkLost ( false )
	, VSizeProvide ( 0 )
	, VSizeReq ( 0 )
	, VStatsRx ( 0 )
	, VStatsTx ( 0 )
	, VTCPackList (   )
	, VTMPackList (   )
	, VTryNumber ( 0 )
	, EDROOMPoolCDTMTCCommServer ( SIZE_OF_POOLS, pEDROOMMemory->poolCDTMTCCommServer, pEDROOMMemory->poolMarkCDTMTCCommServer)
	, EDROOMPoolCDDataBurst ( SIZE_OF_POOLS, pEDROOMMemory->poolCDDataBurst, pEDROOMMemory->poolMarkCDDataBurst)
	, EDROOMPoolCDBurst ( SIZE_OF_POOLS, pEDROOMMemory->poolCDBurst, pEDROOMMemory->poolMarkCDBurst)
{

}

	// EDROOMBehaviour**********************************************

void CASGI::EDROOMTopState::EDROOMBehaviour(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans = EDROOMIllegada();

	do{

		switch(edroomCurrentTrans.localId){

			case(Init):
				edroomNextState = StandBy;
				break;
			case(ToComm):
				FToComm();
				edroomNextState = SendingSATReady;
				break;
			case(TxSATReadyRxBurst):
				FSendReady();

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( GIsSatControl() ){
					edroomCurrentTrans.localId = TxSATReadyRxBurst_ToSATControl;
					edroomNextState = SATControl;
				 } 
				else if( GIsSenTMTCDelivery() ){
					edroomCurrentTrans.localId = TxSATReadyRxBurst_ToSenTMTCDelivery;
					edroomNextState = SenTMTCDelivery;
				 } 
				else if( GLinkLost() ){
					edroomCurrentTrans.localId = TxSATReadyRxBurst_LinkLost;
					edroomNextState = CommInterrupted;
				 } 
				else{
					edroomCurrentTrans.localId = TxSATReadyRxBurst_AnswerFail;
					edroomNextState = SendingSATReady;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
			case(KeepOnComm):
				FKeepOnComm();
				edroomNextState = SendingSATReady;
				break;
			case(ToStandBy):
				FToStandby();
				edroomNextState = StandBy;
				break;
		}

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(I):
				edroomCurrentTrans=EDROOMIllegada();
				break;

			case(StandBy):
				
				edroomCurrentTrans=EDROOMStandByllegada();
				break;

			case(SendingSATReady):
				FProgSATReady();
				edroomCurrentTrans=EDROOMSendingSATReadyllegada();
				break;

			case(SATControl):
				edroomCurrentTrans=EDROOMSATControl.llegada((IdTrans)edroomCurrentTrans.localId);
				break;

			case(SenTMTCDelivery):
				edroomCurrentTrans=EDROOMSenTMTCDelivery.llegada((IdTrans)edroomCurrentTrans.localId);
				break;

			case(CommInterrupted):
				FCommInterrupted();
				edroomCurrentTrans=EDROOMCommInterruptedllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

	}while(Msg->signal != EDROOMSignalDestroy);

}



	// Inicio**********************************************

void CASGI::EDROOMTopState::EDROOMInicio(){

EDROOMSATControl.EDROOMInicio();
EDROOMSenTMTCDelivery.EDROOMInicio();
edroomCurrentState=I;

}



//	 ***********************************************************************

//	 llegada SubEstado I

//	 ***********************************************************************



TEDROOMTransId CASGI::EDROOMTopState::EDROOMIllegada(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans.localId = Init;
	edroomCurrentTrans.distanceToContext = 0;
	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, 0);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja StandBy

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOMTopState::EDROOMStandByllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (SToComm): 

				 if ( *Msg->GetPInterface() == PlannerSGIControl) {

					edroomCurrentTrans.localId= ToComm;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja SendingSATReady

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOMTopState::EDROOMSendingSATReadyllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == SATReadyTimer) {

					edroomCurrentTrans.localId = TxSATReadyRxBurst;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja CommInterrupted

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOMTopState::EDROOMCommInterruptedllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



// ***********************************************************************

// class EDROOM_SUB_SATControl_3

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CASGI::EDROOM_SUB_SATControl_3::EDROOM_SUB_SATControl_3(EDROOMTopContext::edroomStateId idEst, EDROOMTopContext &contex ):
	  EDROOM_CTX_SATControl_3( contex  )
{ idEstado =idEst; }

	// llegada**********************************************

TEDROOMTransId CASGI::EDROOM_SUB_SATControl_3::llegada(EDROOMTopContext::IdTrans transLlegada){

	TEDROOMTransId edroomCurrentTrans;

	int salirContexto;

	switch (transLlegada){

		case(EDROOMTopContext::TxSATReadyRxBurst_ToSATControl):

		EDROOMcomponent.EDROOMTraceStateEntry();

			if( GIsNotLastTCBurst() ){
				edroomNextState = WaitTCFrames;
				edroomCurrentTrans.localId = EntryToSATControl_TCNotCompleted;
			}
			else{
				FSendTCPacketsToTMTCServer();
				edroomNextState = SendingTM;
				edroomCurrentTrans.localId = EntryToSATControl_TCCompleted;
			}
			EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
			break;
		case(EDROOMTopContext::EDROOMMEMORIA):
			edroomCurrentTrans.localId = EDROOMMEMORIA ;
			edroomNextState = edroomCurrentState;
			break;
		default:
			edroomCurrentTrans.localId = EDROOMMEMORIA ;
			edroomNextState = edroomCurrentState;
			break;
	}

	do{

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(WaitTCFrames):
				FProgSATTC();
				edroomCurrentTrans=EDROOMWaitTCFramesllegada();
				break;

			case(SendingTM):
				FProgSATTM();
				edroomCurrentTrans=EDROOMSendingTMllegada();
				break;

			case(CommInterrupted):
				FCommInterrupted();
				edroomCurrentTrans=EDROOMCommInterruptedllegada();
				break;

			case(TxTMCompleted):
				FTxTMCompleted();
				edroomCurrentTrans=EDROOMTxTMCompletedllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

		if (edroomCurrentTrans.distanceToContext == 0){

			switch (edroomCurrentTrans.localId){

				case(TxTCAcksRxTCFrames):
					FSendTCAck();

					EDROOMcomponent.EDROOMTraceStateEntry();

					if( GIsNotLastTCBurst() ){
						edroomCurrentTrans.localId = TxTCAcksRxTCFrames_TCNotCompleted;
						edroomNextState = WaitTCFrames;
						salirContexto=0;
					 } 
					else if( GLinkLost() ){
						edroomCurrentTrans.localId = TxTCAcksRxTCFrames_LinkLost;
						edroomNextState = CommInterrupted;
						salirContexto=0;
					 } 
					else{
						FSendTCPacketsToTMTCServer();
						edroomCurrentTrans.localId = TxTCAcksRxTCFrames_TCCompleted;
						edroomNextState = SendingTM;
						salirContexto=0;
					 } 
					EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
					break;
				case(TxTMFramesRxTMAck):
					FSendTM();

					EDROOMcomponent.EDROOMTraceStateEntry();

					if( GLastTMBurst() ){
						edroomCurrentTrans.localId = TxTMFramesRxTMAck_TMFramesPending;
						edroomNextState = SendingTM;
						salirContexto=0;
					 } 
					else if( GLinkLost() ){
						edroomCurrentTrans.localId = TxTMFramesRxTMAck_LinkLost;
						edroomNextState = CommInterrupted;
						salirContexto=0;
					 } 
					else{
						edroomCurrentTrans.localId = TxTMFramesRxTMAck_NoTMFramesPending;
						edroomNextState = TxTMCompleted;
						salirContexto=0;
					 } 
					EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
					break;
			}

		}else salirContexto=1;

	}while(!salirContexto);

	edroomCurrentTrans.distanceToContext--;

	return(edroomCurrentTrans);

}



	// Inicio**********************************************

void CASGI::EDROOM_SUB_SATControl_3::EDROOMInicio(){

}



	// ***********************************************************************

	// llegada SubEstado Hoja WaitTCFrames

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SATControl_3::EDROOMWaitTCFramesllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == TxRxBurstTimer) {

					edroomCurrentTrans.localId = TxTCAcksRxTCFrames;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja SendingTM

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SATControl_3::EDROOMSendingTMllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == TxRxBurstTimer) {

					edroomCurrentTrans.localId = TxTMFramesRxTMAck;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja CommInterrupted

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SATControl_3::EDROOMCommInterruptedllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja TxTMCompleted

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SATControl_3::EDROOMTxTMCompletedllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



// ***********************************************************************

// class EDROOM_SUB_SenTMTCDelivery_4

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CASGI::EDROOM_SUB_SenTMTCDelivery_4::EDROOM_SUB_SenTMTCDelivery_4(EDROOMTopContext::edroomStateId idEst, EDROOMTopContext &contex ):
	  EDROOM_CTX_SenTMTCDelivery_4( contex , VBurstType, VSendDel )
	, VBurstType ( BurstTypeIsSGIDefault )
	, VSendDel ( false )
{ idEstado =idEst; }

	// llegada**********************************************

TEDROOMTransId CASGI::EDROOM_SUB_SenTMTCDelivery_4::llegada(EDROOMTopContext::IdTrans transLlegada){

	TEDROOMTransId edroomCurrentTrans;

	int salirContexto;

	switch (transLlegada){

		case(EDROOMTopContext::TxSATReadyRxBurst_ToSenTMTCDelivery):
			edroomCurrentTrans.localId= EntryToTmTcDelivery;
			edroomNextState = Accept;
			break;
		case(EDROOMTopContext::EDROOMMEMORIA):
			edroomCurrentTrans.localId = EDROOMMEMORIA ;
			edroomNextState = edroomCurrentState;
			break;
		default:
			edroomCurrentTrans.localId = EDROOMMEMORIA ;
			edroomNextState = edroomCurrentState;
			break;
	}

	do{

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(Accept):
				FProgAccept();
				edroomCurrentTrans=EDROOMAcceptllegada();
				break;

			case(Loading):
				FProgSenLoad();
				edroomCurrentTrans=EDROOMLoadingllegada();
				break;

			case(TMTCDeliveryCompleted):
				FTxTMTCDeliveryCompleted();
				edroomCurrentTrans=EDROOMTMTCDeliveryCompletedllegada();
				break;

			case(CommInterrupted):
				FCommInterrupted();
				edroomCurrentTrans=EDROOMCommInterruptedllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

		if (edroomCurrentTrans.distanceToContext == 0){

			switch (edroomCurrentTrans.localId){

				case(SendAccept):
					FSendAccept();

					EDROOMcomponent.EDROOMTraceStateEntry();

					if( GLinkLost() ){
						edroomCurrentTrans.localId = SendAccept_LinkLost;
						edroomNextState = CommInterrupted;
						salirContexto=0;
					 } 
					else if( GResponseAccept() ){
						edroomCurrentTrans.localId = SendAccept_ReceiveOk;
						edroomNextState = Loading;
						salirContexto=0;
					 } 
					else{
						edroomCurrentTrans.localId = SendAccept_NotOk;
						edroomNextState = Accept;
						salirContexto=0;
					 } 
					EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
					break;
				case(Load):
					FSendDown();

					EDROOMcomponent.EDROOMTraceStateEntry();

					if( GNotCompleted() ){
						edroomCurrentTrans.localId = Load_NotCompleted;
						edroomNextState = Loading;
						salirContexto=0;
					 } 
					else if( GLinkLost() ){
						edroomCurrentTrans.localId = Load_LinkLost;
						edroomNextState = CommInterrupted;
						salirContexto=0;
					 } 
					else{
						edroomCurrentTrans.localId = Load_Completed;
						edroomNextState = TMTCDeliveryCompleted;
						salirContexto=0;
					 } 
					EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
					break;
			}

		}else salirContexto=1;

	}while(!salirContexto);

	edroomCurrentTrans.distanceToContext--;

	return(edroomCurrentTrans);

}



	// Inicio**********************************************

void CASGI::EDROOM_SUB_SenTMTCDelivery_4::EDROOMInicio(){

}



	// ***********************************************************************

	// llegada SubEstado Hoja Accept

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SenTMTCDelivery_4::EDROOMAcceptllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == TxRxBurstTimer) {

					edroomCurrentTrans.localId = SendAccept;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja Loading

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SenTMTCDelivery_4::EDROOMLoadingllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == TxRxBurstTimer) {

					edroomCurrentTrans.localId = Load;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja TMTCDeliveryCompleted

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SenTMTCDelivery_4::EDROOMTMTCDeliveryCompletedllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja CommInterrupted

	// ***********************************************************************



TEDROOMTransId CASGI::EDROOM_SUB_SenTMTCDelivery_4::EDROOMCommInterruptedllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



